package cn.com.captureNetPacket;

import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.FileTime;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;

import cn.com.captureNetPacket.model.*;
import org.jnetpcap.Pcap;
import org.jnetpcap.PcapAddr;
import org.jnetpcap.PcapBpfProgram;
import org.jnetpcap.PcapIf;
import org.jnetpcap.nio.JBuffer;
import org.jnetpcap.nio.JMemory;
import org.jnetpcap.winpcap.WinPcap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import cn.com.captureNetPacket.dependThirdParty.DependThirdPartyService;
import cn.com.captureNetPacket.iatConfig.IatConfig;
import cn.com.captureNetPacket.model.StaticVar.DEVICE_TYPE;
import cn.com.captureNetPacket.util.JsonPathUtil;
import cn.com.captureNetPacket.util.LinsencesTools;
import cn.com.captureNetPacket.util.RedisConfig;
import cn.com.captureNetPacket.util.SpringUtil;
import cn.com.captureNetPacket.util.Tools;
import cn.com.captureNetPacket.voice.AnalysisRTP;
import cn.com.captureNetPacket.voice.AnalysisSIP;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import static cn.com.captureNetPacket.model.StaticVar.NETWORKCARD_STATUS.*;

@Slf4j
@Component
@EnableScheduling
public class CaptureNetPacketService {
	static {
//		https://blog.csdn.net/qq_39620460/article/details/89736721  参看
//		System.setProperty("org.jnetsoft.nio.MaxDirectMemorySize", "5gb");
//		System.setProperty("org.jnetsoft.nio.SoftDirectMemorySize", "5gb");
	}
public static  CaptureNetPacketService captureNetPacketServiceStatic;
	
	public static CaptureNetPacketService getCaptureNetPacketService() {
		return captureNetPacketServiceStatic;
	}
	 
	
	// 标识core 程序
	public static final int appId=0;
	
	 @Value("${cnp.clusterServerId}")
	private String clusterServerId;
	 @Value("${cnp.linsence.secretKey}")
	 private String secretKey;
	 @Value("${cnp.linsence.linsencesContent}")
	 private String linsencesContent;
	 private static int maxChannelCount=10;
 
	 // 读取的授权信息
	 private int licNeedPushRealTimeTransmissionDataMaxCount;
	 private int licRecordMaxCount;
	 private String licHostName;
	 private List<String> licIPAddress;
	 
	 
	 private static String clusterServId;
	 
	 
	 /**
	  * 开启对接第三方信令
	  */
	 @Value("${cnp.dependThirdParty.enable}")
	 private   boolean dependThirdPartyEnable;
	 
	 /**
	  *  对接第三方信令使用的beanName
	  */
	 @Value("${cnp.dependThirdParty.dependThirdPartyBeanName}")
	 private   String dependThirdPartyBeanName;
	 
	 
	 /**
	  * iat 开启
	  */
	 
	 @Value("${cnp.iat.enable}")
	 private   boolean iatEnable;
	 /**
	  * iat 初始化使用的beanName
	  */
	@Value("${cnp.iat.iatConfigBeanName}")
	private   String iatConfigBeanName;
		
		
		 
		
		
	 
	 private static long waitDeviceStatusTimeOut=1000;
	
	
//	private static IflytekConfig iflytekConfig=new IflytekConfig();
	
	
	// 存放所有的设备信息
	private static ConcurrentHashMap<String,DeviceInfo> deviceInfos=new ConcurrentHashMap<String, DeviceInfo>();
	// 存放所有的分机信息
	private static ConcurrentHashMap<String,DeviceInfo> stationDeviceInfos=new ConcurrentHashMap<String, DeviceInfo>();
	// 存放其他通道信息
	private static ConcurrentHashMap<String,DeviceInfo> otherDeviceInfos=new ConcurrentHashMap<String, DeviceInfo>();
	private static ConcurrentHashMap<String,DeviceStatus> deviceStatus=new ConcurrentHashMap<String, DeviceStatus>();
	private static DependThirdPartyService dependThirdPartyService;
	private static IatConfig iatConfig;
	
	public List<NetworkCardInfo> networkCardInfos;
	public static  boolean ipLogOpen=false;
	public static  boolean tcpLogOpen=false;
	public static  boolean udpLogOpen=false;
	
	public static  boolean analysisIP4Unknown=false;
	public static  boolean IP4UnknownLogOpen=false;
	public static  boolean analysisTcp=false;
	public static  boolean analysisSip=false;
	public static  boolean analysisUdp=false;
	public static  boolean analysisRtp=false;
	public static  int timeOutPacket=5000;

	/**
	 *  重启计数的阀值等级
	 */
	public static  int exitCountThresholdLeval=3;


	public static  int surplus=11;
	//应用层的超时时间
	public static  int hertTimeOutPacket=5000;

    /**
     *  fluctuationRange 波动幅度,网络抖动最大值，目前测试相近的两个包seq值大概最大是120秒。单位毫秒。
     */
	private static long fluctuationRange=120000;
	/**
	 * 网络抖动的后最大丢包数量
	 */
	private static long fluctuationRangeMaxLosePackets=600;
	public final static DateTimeFormatter tempFileDF = DateTimeFormatter.ofPattern("yyyy_MM_dd_HH_mm_ss_SSSSSS");
	public final static DateTimeFormatter fileDF = DateTimeFormatter.ofPattern("yyyy_MM_dd_HH_mm_ss");
	public final static DateTimeFormatter dirDF = DateTimeFormatter.ofPattern("yyyyMMdd");
	private static Executor taskService;
	private static ConfigData appConfig;
	public  static Properties props;
	public static Executor getTaskService() {
		 
		return taskService;
	}
	public static ConfigData getAppConfig() {
		return appConfig;
	}
	public static ConcurrentHashMap<String, DeviceInfo> getDeviceInfos() {
		return deviceInfos;
	}
	public static ConcurrentHashMap<String, DeviceInfo> getStationDeviceInfos() {
		return stationDeviceInfos;
	}
	public static ConcurrentHashMap<String, DeviceInfo> getOtherDeviceInfos() {
		return otherDeviceInfos;
	}
	public static ConcurrentHashMap<String, DeviceStatus> getDeviceStatus() {
		return deviceStatus;
	}
	public static DependThirdPartyService  getDependThirdPartyService() {
		return dependThirdPartyService;
	}
	public static IatConfig  getIatConfig() {
		return iatConfig;
	}
	 
	public static String getClusterServId() {
		return clusterServId;
	}
	public static long getWaitDeviceStatusTimeOut() {
		return waitDeviceStatusTimeOut;
	}
	public static int getMaxChannelCount() {
		return maxChannelCount;
	}

	/**
	 * 数据包波动大小。  与上一个包的时间差容忍度。 毫秒
	 * @return
	 */
	public static long getFluctuationRange(){
		return fluctuationRange;
	}


	public static long getFluctuationRangeMaxLosePackets(){
		return fluctuationRangeMaxLosePackets;
	}

	public CorePcapPacketHandler corePcapPacketHandler=null;
	@Autowired
    @Qualifier(value = "asyncServiceExecutor")
    private Executor asyncServiceExecutor;
	
    @Autowired
    private   SpringUtil   springUtil;
	
//	public Pcap pcap;


	/**
	 *   需要抓取的网卡所有.key为 网卡名称或者IPv4、IPv6的IP，获取的时候注意使用这三个作为key
 	 */

	Map<String,NetworkCardInfo> openNetworkCards=new HashMap();


	/**
	 *
	 读取抓包文件的信息当做一块网卡处理。
	 */
	NetworkCardInfo openNetworkFileCard=null;
	StringBuilder errbuf ;     // For any error msgs
      public void initNetworkCardInfo (){
    	  NetworkCardInfo nci;int index=0;
    	  networkCardInfos=new ArrayList<NetworkCardInfo>();
    		 List<PcapIf> alldevs = new ArrayList<PcapIf>(); // Will be filled with NICs
    		 errbuf = new StringBuilder();     // For any error msgs
   	      StringBuilder mac=new StringBuilder(); 
           int r=  	Pcap.findAllDevs(alldevs, errbuf);
             	
               if (r != Pcap.OK || alldevs.isEmpty()) {  
               	log.error("-----------networkCard isEmpty or get net");
               	log.info("errbuf:"+errbuf.toString());
               	return ;
               }  
               log.info("网卡数量:"+alldevs.size());
             	log.info("\r\n\r\n");
             	log.info("配置了需要监听的网卡: {}", appConfig.getMonitorNetworkCardIP());
               
               for(PcapIf pcapIf:alldevs){
            	   index++;
            	   nci=new NetworkCardInfo();
               	mac=new StringBuilder();

               	try {
               		nci.setName(pcapIf.getName());
               		nci.setFlags(pcapIf.getFlags());
               		nci.setDescription(pcapIf.getDescription());
               		if(canGtSystemPlatformMAC())
             		nci.setHardwareAddress(Tools.macAsString(pcapIf.getHardwareAddress()));
               		String fistAddr =" no IP";
               		if(pcapIf.getAddresses() !=null)
               		if(pcapIf.getAddresses().size()>0)
               				fistAddr = pcapIf.getAddresses().get(0).getAddr().toString();
               		log.info("第 {} 网卡信息\t名字 : [{}] \t网卡描述: {} \t标示位: {} \t第一IP地址: {}\t物理地址:{}",index,pcapIf.getName(),pcapIf.getDescription(),pcapIf.getFlags(),fistAddr,nci.getHardwareAddress());
               		for(PcapAddr pa:pcapIf.getAddresses()){
               			String temp="0";
               			if(pa.getAddr().toString().contains("INET4")){
               				nci.getIpv4().add(pa.getAddr().toString().substring(7).replaceAll("[\\[\\]]", ""));
               				temp=pa.getNetmask().toString().replaceAll("[\\[\\]]", "");
               			 	temp=temp.replaceAll("INET4:", "");
               				nci.getIpv4Mask().add(temp);
               			}
               			else if (pa.getAddr().toString().contains("INET6")){
               				nci.getIpv6().add(pa.getAddr().toString().substring(7).replaceAll("[\\[\\]]", ""));
               				temp=pa.getNetmask().toString().replaceAll("[\\[\\]]", "");
               		      	temp=temp.replaceAll("INET6:", "");
               				nci.getIpv6Mask().add(temp);
               			}

               			
               			
               			
               			try {
               				if(appConfig.getMonitorNetworkCardIP().contains( nci.getName().trim()))
//               					monitorNetworkCardInfo=nci;
								openNetworkCards.put(nci.getName(),nci);
               			}catch (Exception e) {
//               				log.error("name match error",e);
               			}
               			try {
               				if(nci.getIpv4().size()>0)
               			if(appConfig.getMonitorNetworkCardIP().contains(nci.getIpv4().get(0)))
//               				monitorNetworkCardInfo=nci;
							openNetworkCards.put(nci.getIpv4().get(0),nci);
               			}catch (Exception e) {
//						 log.error("IPv4 match error",e);
						}
               			try {
               				if(nci.getIpv6().size()>0)
               			if(appConfig.getMonitorNetworkCardIP().contains(nci.getIpv6().get(0)))
//               				monitorNetworkCardInfo=nci;
							openNetworkCards.put(nci.getIpv6().get(0),nci);
               			}catch (Exception e) {
//               				log.error("IPv6 match error",e);
						}
               			log.info("ip:"+pa.getAddr()+" netmask:"+pa.getNetmask()+" broadaddr:"+pa.getBroadaddr()+" Dstaddr:"+pa.getDstaddr());
               		}
               	 
                   } catch (Exception e) {
               		log.error("initNetworkCardInfo:",e);
   				}
               	log.info("一块信息获取完成\r\n\r\n");
               }
			   // 去重
//		  networkCardInfos=networkCardInfos.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(()
//				  -> new TreeSet<>(Comparator.comparing(ncit-> ncit.getName()))), ArrayList::new));
               log.info("所有网卡共{}块信息获取完成：{}",openNetworkCards.size(),openNetworkCards);
               

 }


	/**
	 *  初始化读取抓包文件的信息。
	 */
	public void initNetworkFileCardInfo(){
		if(!StringUtils.hasText(appConfig.getFilePath())){
          return;
		}

		try{
			openNetworkFileCard=new NetworkCardInfo();
			openNetworkFileCard.setName("pcapfile");
			openNetworkFileCard.setHardwareAddress(appConfig.getFilePath());
			openNetworkFileCard.setDescription("<<读取抓包网卡初始化的pcap>>");
			openNetworkFileCard.setFlags(1);
		}catch (Exception e){
			log.error("initNetworkFileCardInfo 初始化读取抓包文件失败,读取的路径:{} ",appConfig.getFilePath(),e);
		}

	}
	
      /***************************************
           * 打开选中的设备
           * 
           * 
           *  // openlive方法：这个方法打开一个和指定网络设备有关的，活跃的捕获器 

            // 参数：snaplen指定的是可以捕获的最大的byte数，
            // 如果 snaplen的值 比 我们捕获的包的大小要小的话，
            // 那么只有snaplen大小的数据会被捕获并以packet data的形式提供。
            // IP协议用16位来表示IP的数据包长度，所有最大长度是65535的长度
            // 这个长度对于大多数的网络是足够捕获全部的数据包的

            // 参数：flags promisc指定了接口是promisc模式的，也就是混杂模式，
            // 混杂模式是网卡几种工作模式之一，比较于直接模式：
            // 直接模式只接收mac地址是自己的帧，
            // 但是混杂模式是让网卡接收所有的，流过网卡的帧，达到了网络信息监视捕捉的目的

            // 参数：timeout 这个参数使得捕获报后等待一定的时间，来捕获更多的数据包，
            // 然后一次操作读多个包，不过不是所有的平台都支持，不支持的会自动忽略这个参数

            // 参数：errbuf pcap_open_live()失败返回NULL的错误信息，或者成功时候的警告信息         


        ***************************************/
      public void openDrive(NetworkCardInfo monitorNetworkCardInfo){
		  monitorNetworkCardInfo.setNetworkCaptureStaus(StaticVar.NETWORKCARD_STATUS.INITIALIZING);
    	  log.info("\r\n\r\n选择打开网卡《"+monitorNetworkCardInfo.getName()+"》网卡物理地址："+monitorNetworkCardInfo.getHardwareAddress()+" 描述信息："+monitorNetworkCardInfo.getDescription());
    	  if(monitorNetworkCardInfo.getIpv4()!=null && monitorNetworkCardInfo.getIpv4().size()>0)
    	  if(monitorNetworkCardInfo.getIpv4().get(0)!=null)
    		  log.info(" 第一IPV4地址为:"+monitorNetworkCardInfo.getIpv4().get(0)+" 掩码地址："+monitorNetworkCardInfo.getIpv4Mask().get(0));
    	  if(monitorNetworkCardInfo.getIpv6()!=null&& monitorNetworkCardInfo.getIpv6().size()>0)
    	  if(monitorNetworkCardInfo.getIpv6().get(0)!=null)
    		  log.info(" 第一IPV6地址为:"+monitorNetworkCardInfo.getIpv6().get(0)+" 掩码地址："+monitorNetworkCardInfo.getIpv6Mask().get(0));
		  StringBuilder errbuf ;     // For any error msgs
    	    errbuf = new StringBuilder();     // For any error msgs，errbuf是用来返回错误或警告文字。
          int snaplen = Pcap.DEFAULT_SNAPLEN;          // Capture all packets, no trucation,最大字节数，最大65535
               int flags = Pcap.MODE_PROMISCUOUS; // capture all packets，混杂模式，true表示打开混杂模式
              int timeout = timeOutPacket<0?0:timeOutPacket;           // 10 seconds in millis，读取超时   to_ms是读取时的超时值，单位是毫秒(假如为0则一直嗅探直到错误发生，为-1则不确定)。之前设置的30秒。
              log.info("openLive {} 读取超时时间 {}",monitorNetworkCardInfo.getName(),timeout);
              Pcap pcap;
//                pcap = Pcap.openLive(monitorNetworkCardInfo.getName(), snaplen, flags, timeout, errbuf);
                pcap = Pcap.openLive(monitorNetworkCardInfo.getName(), snaplen, flags,0, errbuf);

              if (pcap == null) {
				  monitorNetworkCardInfo.setNetworkCaptureStaus(StaticVar.NETWORKCARD_STATUS.OPEN_FAIL);
				  log.error("网卡打开失败。网卡名:{} Error while opening device for capture  。 打开的错误信息: {}",monitorNetworkCardInfo.getName(), errbuf.toString());
                 return;
             }
//			   设置缓存大小，256M
//		  要设置的缓冲区大小是pcap_set_buffer_size()指(ring-)缓冲区,它存储已接收的包.最佳大小取决于用例和经济实惠的系统资源(不可分页的内存).
//				  有关接收缓冲区大小的详细信息请参见以下语句 man pcap:
//		  到达捕获的数据包存储在缓冲区中,因此应用程序一到达就不必读取它们.在某些平台上,可以设置缓冲区的大小; 太小的大小可能意味着,如果捕获太多数据包并且快照长度不限制缓冲的数据量,如果缓冲区在应用程序可以从其中读取数据包之前填满,则可以丢弃数据包,同时太大的大小可能会使用更多不可分页的操作系统内存,而不是防止数据包被丢弃.
//		  pcap.setBufferSize(20*1024*1024);
              log.info("openLive {} success errbuf: {} !!!",monitorNetworkCardInfo.getName(),errbuf);
	/*	  若pcap_setnonblock(0)，表示阻塞模式，pcap_dispatch只有在mintocopy满，或者是timeout到时才返回，返回捕捉到的数据包数
		  pcap_setnonblock(1)，非阻塞，立即返回
				  pcap_loop相当于多次调用了pcap_dispatch*/
		       pcap.setNonBlock(1,errbuf);
		  log.info("openLive {} setNonBlock success errbuf: {} !!!",monitorNetworkCardInfo.getName(),errbuf);
              monitorNetworkCardInfo.setPcap(pcap);

              // 设置过滤器
              
              
		           if(appConfig.getFilterExpression()!=null && appConfig.getFilterExpression().trim().length()>0) {
		              PcapBpfProgram filter = new PcapBpfProgram();
		      		String expression = appConfig.getFilterExpression();
//		    表达式参考  		https://www.wireshark.org/docs/man-pages/pcap-filter.html
		//              pcap.compile(PcapBpfProgram program, String expression, int optimize, int netmask) 
		//                        参数一是第一步创建的filter，
		//                       参数二是expression过滤表达式，
		//                       参数三是是否优化（1表示进行优化，任何其他值表示否），
		//                       参数四是确定广播地址所需的网络掩码（仅仅过滤可以无视），
		//                       重点是前两个参数，返回值用于确定表达式是否符合规范，返回-1表示有错误。
		      		 int res = pcap.compile(filter, expression, 1, 0);
		      		 pcap.setFilter(filter);
					   pcap.setTimeout(0);
					   pcap.setTimeout(timeout);
		      		 if (res != 0) {
		      			log.info("网卡 {} Filter error：{}" ,monitorNetworkCardInfo.getName(), pcap.getErr());
		      		 }
					   monitorNetworkCardInfo.setNetworkCaptureStaus(StaticVar.NETWORKCARD_STATUS.OPENED);
		      		 log.info("网卡 {} set filter expression: \"{}\" success  !!!",monitorNetworkCardInfo.getName(),expression);
		      }

      }


	/**
	 *  打开读取文件文件
	 * @param monitorNetworkCardInfo 读取抓包文件的配置信息
	 * @param fileName  读取的文件名
	 */
	public void openFileDrive(NetworkCardInfo monitorNetworkCardInfo,String fileName){
		monitorNetworkCardInfo.setNetworkCaptureStaus(StaticVar.NETWORKCARD_STATUS.INITIALIZING);
		log.info("\r\n\r\n打开抓包文件。《"+monitorNetworkCardInfo.getName()+"》 文件路径："+monitorNetworkCardInfo.getHardwareAddress()+" 文件名："+fileName);

		StringBuilder errbuf ;     // For any error msgs
		errbuf = new StringBuilder();     // For any error msgs，errbuf是用来返回错误或警告文字。
		int snaplen = Pcap.DEFAULT_SNAPLEN;          // Capture all packets, no trucation,最大字节数，最大65535
		int flags = Pcap.MODE_PROMISCUOUS; // capture all packets，混杂模式，true表示打开混杂模式
		int timeout = timeOutPacket<0?0:timeOutPacket;           // 10 seconds in millis，读取超时   to_ms是读取时的超时值，单位是毫秒(假如为0则一直嗅探直到错误发生，为-1则不确定)。之前设置的30秒。
//		log.info("openLive {} 设置的读取超时时间 {}",monitorNetworkCardInfo.getName(),timeout);
		Pcap pcap =null;
//		log.error("--->>>>>>>打开抓包文件。《{}》",fileName);
		pcap =  Pcap.openOffline(fileName,errbuf);

		if (pcap == null) {
			monitorNetworkCardInfo.setNetworkCaptureStaus(StaticVar.NETWORKCARD_STATUS.OPEN_FAIL);
			log.error("文件夹下 {} 的 {} 文件打开失败。 Error while opening device  for capture ,错误信息: {}",monitorNetworkCardInfo.getHardwareAddress(),fileName, errbuf.toString());
			monitorNetworkCardInfo.setPcap(null);
			return;
		}
//		pcap.setBufferSize(200*1024*1024);
//			   设置缓存大小，256M
//		  要设置的缓冲区大小是pcap_set_buffer_size()指(ring-)缓冲区,它存储已接收的包.最佳大小取决于用例和经济实惠的系统资源(不可分页的内存).
//				  有关接收缓冲区大小的详细信息请参见以下语句 man pcap:
//		  到达捕获的数据包存储在缓冲区中,因此应用程序一到达就不必读取它们.在某些平台上,可以设置缓冲区的大小; 太小的大小可能意味着,如果捕获太多数据包并且快照长度不限制缓冲的数据量,如果缓冲区在应用程序可以从其中读取数据包之前填满,则可以丢弃数据包,同时太大的大小可能会使用更多不可分页的操作系统内存,而不是防止数据包被丢弃.
//		pcap.setBufferSize(1024*102481024);
		log.info("openLive {} success errbuf: {} !!!",monitorNetworkCardInfo.getName(),errbuf);
	/*	  若pcap_setnonblock(0)，表示阻塞模式，pcap_dispatch只有在mintocopy满，或者是timeout到时才返回，返回捕捉到的数据包数
		  pcap_setnonblock(1)，非阻塞，立即返回
				  pcap_loop相当于多次调用了pcap_dispatch*/
		pcap.setNonBlock(1,errbuf);
		log.info("openLive {} setNonBlock success errbuf: {} !!!",monitorNetworkCardInfo.getName(),errbuf);
		monitorNetworkCardInfo.setPcap(pcap);

		// 设置过滤器


		if(appConfig.getFileFilterExpression()!=null && appConfig.getFileFilterExpression().trim().length()>0) {
			PcapBpfProgram filter = new PcapBpfProgram();
			String expression = appConfig.getFileFilterExpression();
//		    表达式参考  		https://www.wireshark.org/docs/man-pages/pcap-filter.html
			//              pcap.compile(PcapBpfProgram program, String expression, int optimize, int netmask) 
			//                        参数一是第一步创建的filter，
			//                       参数二是expression过滤表达式，
			//                       参数三是是否优化（1表示进行优化，任何其他值表示否），
			//                       参数四是确定广播地址所需的网络掩码（仅仅过滤可以无视），
			//                       重点是前两个参数，返回值用于确定表达式是否符合规范，返回-1表示有错误。
			int res = pcap.compile(filter, expression, 1, 0);
			pcap.setFilter(filter);
			pcap.setTimeout(0);
			pcap.setTimeout(timeout);
			if (res != 0) {
				log.warn("网卡 {} Filter error：{}" ,monitorNetworkCardInfo.getName(), pcap.getErr());
			}
			monitorNetworkCardInfo.setNetworkCaptureStaus(StaticVar.NETWORKCARD_STATUS.OPENED);
			log.info("网卡 {} set filter expression: \"{}\" success  !!!",monitorNetworkCardInfo.getName(),expression);
		}

	}


	/**
	 *  关闭设备
	 * @param monitorNetworkCardInfo
	 */
	public void closeDrive(NetworkCardInfo monitorNetworkCardInfo){
		monitorNetworkCardInfo.setNetworkCaptureStaus(StaticVar.NETWORKCARD_STATUS.DESTRYOYING);
		log.info("closeDrive {} 正在关闭网卡 !!!",monitorNetworkCardInfo.getName());
		if(monitorNetworkCardInfo.getReCapCount()>2*exitCountThresholdLeval-1) {
			log.error("closeDrive {} 重启网卡次数{}次，直接退出程序。当前线程ID: {}",monitorNetworkCardInfo.getName(),monitorNetworkCardInfo.getReCapCount(),monitorNetworkCardInfo.getLoadPacketThread().getId());
			System.exit(0);
		}
		try{
			if(monitorNetworkCardInfo.getPcap()!=null && monitorNetworkCardInfo.getNetworkCaptureStaus().getValue()>-1 && monitorNetworkCardInfo.getReCapCount()>exitCountThresholdLeval+1){
				monitorNetworkCardInfo.getPcap().close();
				monitorNetworkCardInfo.setPcap(null);
				log.info("closeDrive {} 网卡关闭成功 !!! Pcap close 。当前线程ID: {}",monitorNetworkCardInfo.getName(),monitorNetworkCardInfo.getLoadPacketThread().getId());
			}else {
				monitorNetworkCardInfo.setNeedReinitThread(true);
				log.info("closeDrive {} 网卡关闭成功 !!! 需要只重新初始化线程。当前线程ID: {}",monitorNetworkCardInfo.getName(),monitorNetworkCardInfo.getLoadPacketThread().getId());
			}
		}catch (Exception e){
			log.warn("closeDrive {} 网卡关闭失败!!!",monitorNetworkCardInfo.getName(),e);
		}finally {
			monitorNetworkCardInfo.setNetworkCaptureStaus(StaticVar.NETWORKCARD_STATUS.CLOSED);
		}

	}


      public void startinit() throws Exception{
		if(captureNetPacketServiceStatic!=null){
			log.warn("CaptureNetPacket Application inited.......... 已经初始化过了，无需初始化。");
			return ;
		}
    	  captureNetPacketServiceStatic=this;
    	  log.info("CaptureNetPacket Application Starting.......... august version:20240221");
    	  clusterServId=clusterServerId;
    	  showSystemPlatformInfo();
    	  
    	  log.info("抓包lib需要在此路径下, java.library.path: {}",System.getProperty("java.library.path"));
    	  try {
    	  initStaticConfig();
    	   
    	  
    	  initAppDate();
    	  log.info("CaptureNetPacket Application Starting  init NetworkCard ............");
    	  
    	  initDeviceInfo();
    	  log.info("CaptureNetPacket Application Starting  init DeviceInfo 获取本地网卡信息............");
    	  initNetworkCardInfo();
		  initNetworkFileCardInfo();
    	  }catch (Exception e) {
    		  log.error("startinit fail .........",e);
    		  throw e;
		}

		  Thread watchdogNetworkStartThread=new Thread(() -> {
			  while (true) {
				  try {
					  // 打开配置的网卡进行抓包。
					  networkThreadStartAll();
					  networkFileThreadStartAll();
					  Thread.sleep(30000);
				  }catch (Exception e){
					  log.warn("checkNetworkAndHandel ",e);
				  }
			  }
		  });
		  watchdogNetworkStartThread.setName("watchdogNetworkStartThread-cnp");
		  watchdogNetworkStartThread.setPriority(Thread.MAX_PRIORITY-4);
		  watchdogNetworkStartThread.start();

		  Thread watchdogThread=new Thread(() -> {
			  while (true) {
				  try {
					  checkNetworkAndHandel();
				  }catch (Exception e){
					  log.warn("checkNetworkAndHandel ",e);
				  }
			  }
		  });
		  watchdogThread.setName("watchdogThread-cnp");
		  watchdogThread.setPriority(Thread.MAX_PRIORITY-4);
		  watchdogThread.start();


		  Thread pcapFileThread=new Thread(() -> {
			  while (true) {
				  try {
					  pcapFileAndHandel();
				  }catch (Exception e){
					  log.warn("pcapFileThread ",e);
				  }
			  }
		  });
		  pcapFileThread.setName("pcapFileHandelThread-cnp");
		  pcapFileThread.setPriority(Thread.MAX_PRIORITY-4);
		  pcapFileThread.start();



		  SpringUtil.setSpringUtil(springUtil);
		  log.debug("spring 容器装载完成，开始加载自定义配置信息");
		  SpringUtil.showApplicationInfo();
		  initDependThirdPartyService();
		  initIatConfig();
      }
      
      public void restartinit() {
    	  try {
        	  initStaticConfig();
        	  initDependThirdPartyService();
        	  
        	  initAppDate();
        	  log.info("CaptureNetPacket Application Starting  restartinit NetworkCard ............");
        	  
        	  initDeviceInfo();
        	  log.info("CaptureNetPacket Application Starting  restartinit DeviceInfo ............");
        	  }catch (Exception e) {
        		  log.error("restartinit fail .........",e);
    		}
    	  
      }
      
      /**
       *  添加第三方CTI获取信令的依赖
      	* <strong>Title: 初始化第三方信令的获取<strong>
      	* <p>Description: 添加第三方CTI获取信令的依赖 <p>
      	* <p>Company: </p> 
      	*<strong>Copyright:</strong> Copyright (c) 2019
      	* @version: 1.0
      	* @author  ASUS:augustWei
      	* @date  2021 下午9:48:23
       */
      	private void initDependThirdPartyService() {
		if(dependThirdPartyEnable) {
			dependThirdPartyService=SpringUtil.getUtilBean(dependThirdPartyBeanName);
			if(dependThirdPartyService!=null) {
			dependThirdPartyService.initDependThirdPartyServiceTask();
			}else 
			{
				log.debug("开启了第三方CTI依赖，请检查beanName  当前配置名字: {}。  类名: 首字母小写。",dependThirdPartyBeanName);
			}
		}
		
      	}
      	/**
      	 * 
      		* <strong>Title: 初始化语音iat<strong>
      		* <p>Description: 初始化语音识别平台<p>
      		* <p>Company: </p> 
      		*<strong>Copyright:</strong> Copyright (c) 2019
      		* @version: 1.0
      		* @author  ASUS:augustWei
      		* @date  2021 下午10:34:30
      	 */
      	
      	private void initIatConfig() {
      		if(iatEnable) {
      			iatConfig=SpringUtil.getUtilBean(iatConfigBeanName);
      			if(iatConfig!=null) {
      				iatConfig.initIatConfig();
      				}else 
      				{
      					log.debug("开启了语音识别功能，请检查beanName。 当前配置名字: {} 类名: 首字母小写。",iatConfigBeanName);
      				}
      			 
      		}
      		
      	}
	//初始化日志打印
	private void initAppDate() {
		ipLogOpen= appConfig.isIpLogOpen();
		tcpLogOpen= appConfig.isTcpLogOpen();
		udpLogOpen= appConfig.isUdpLogOpen();
		IP4UnknownLogOpen= appConfig.isIP4UnknownLogOpen();
		
		analysisIP4Unknown= appConfig.isAnalysisIP4Unknown();
		analysisTcp= appConfig.isAnalysisTcp();
		analysisSip= appConfig.isAnalysisSip();
		analysisUdp= appConfig.isAnalysisUdp();
		analysisRtp= appConfig.isAnalysisRtp();
		 
	}
	private void initStaticConfig() throws Exception {
		// 授权的验证
		Map linsensesInfo=LinsencesTools.analysisLinsences(secretKey, linsencesContent);
		licNeedPushRealTimeTransmissionDataMaxCount=(int) linsensesInfo.get("licNeedPushRealTimeTransmissionDataCount");
		licRecordMaxCount= (int) linsensesInfo.get("licRecordCount");
		licHostName=linsensesInfo.get("licHostName").toString();
		licIPAddress=(List) (linsensesInfo.get("licIPAddress")) ;
		log.info("正在对主机名: {} 实际IP: {} 进行授权检查。",hostName,ip);
		if(!licHostName.equals(hostName))throw new Exception("请检查授权，授权的主机名和实际的主机名不相同,授权主机: "+licHostName+" 实际主机名: "+hostName);
		if(!licIPAddress.contains(ip))throw new Exception("请检查授权，授权的主机IP和实际的IP不一致,授权的主机IP: "+licIPAddress.toString()+" 实际IP: "+ip);
		maxChannelCount=	(int) linsensesInfo.get("licChannelCount");
		
		
		log.info("授权针对主机名 :{} IP地址信息: {} 的授权信息，知识随行语音推送: {} 录音授权数量: {}  最大通道数量: {}",licHostName,licIPAddress,licNeedPushRealTimeTransmissionDataMaxCount,licRecordMaxCount,maxChannelCount);

				
		 taskService=asyncServiceExecutor;
		 appConfig =Tools.readConfig();
		 
		 
		 timeOutPacket= appConfig.getTimeOutPacket();
		 hertTimeOutPacket= appConfig.getHertTimeOutPacket()*1000;
		 if(hertTimeOutPacket< appConfig.getRtpPacketTimeOut())
		 {
			 hertTimeOutPacket=(int) (appConfig.getRtpPacketTimeOut()*1.5);
			 log.debug("心跳时间小于，接受包超时时间，心跳时间修改为:{} ，避免出现心跳先与数据包超时的情况，出现获信令消息已经被清楚掉导致取不到信令信息。",hertTimeOutPacket);
		 }

		fluctuationRange=CaptureNetPacketService.getAppConfig().getRtpPacketTimeOut()+1>120000?120000:CaptureNetPacketService.getAppConfig().getRtpPacketTimeOut();
		fluctuationRangeMaxLosePackets=fluctuationRange/20;
		 surplus= appConfig.getSurplus();
		 waitDeviceStatusTimeOut= appConfig.getWaitDeviceStatusTimeOut();
//        超时时间太短，后续操作需要多次才能去做。
		exitCountThresholdLeval=timeOutPacket<60001?5:3;
	}



	public void loadPacket(NetworkCardInfo networkCardInfo) throws InterruptedException {

		log.info("loadPacket 网卡 {} 正在开启抓包ing.....",networkCardInfo.getName());

		if (networkCardInfo.getPcapPacketHandler() == null) {
			networkCardInfo.setPcapPacketHandler(new CorePcapPacketHandler(networkCardInfo));
			networkCardInfo.getPcapPacketHandler().initPcapPacketHandler();
		}

		try {
			while(networkCardInfo.getPcap()!=null && (  networkCardInfo.getNetworkCaptureStaus()== PRE_RUN || networkCardInfo.getNetworkCaptureStaus()==StaticVar.NETWORKCARD_STATUS.AFTER_RUN) ) {
					networkCardInfo.setNetworkCaptureStaus(RUNNING);
				//0标识不断获取数据包  参数 cnt为指定的捕获包的个数 	//cnt=-1,无限捕获 //cnt=0，捕获所有数据包，直到读取到EOF
//			networkCardInfo.getPcap().loop(0,pcapPacketHandler,"jnetpcap");
//			 之前设置的0
//					networkCardInfo.getPcap().loop(0, networkCardInfo.getPcapPacketHandler(), networkCardInfo.getName());
//				log.warn("--{}--------------->><<<<<<>>>>>>>>{}",networkCardInfo.getPcapPacketHandler(),networkCardInfo.getName());
//					networkCardInfo.getPcap().loop(0, networkCardInfo.getPcapPacketHandler(), networkCardInfo.getName());

					networkCardInfo.getPcap().loop(appConfig.getPcapLoopSize(), networkCardInfo.getPcapPacketHandler(), networkCardInfo.getName());
      				networkCardInfo.setNetworkCaptureStaus(StaticVar.NETWORKCARD_STATUS.AFTER_RUN);
			}
		}catch (Exception e){
			networkCardInfo.setNetworkCaptureStaus(StaticVar.NETWORKCARD_STATUS.RUN_EXCEPTION);
			log.error("loadPacket 网卡 {} 抓包出现异常",networkCardInfo.getName(),e);
		}
		log.info("loadPacket 网卡 {} 已正常结束本轮抓包,退出循环。",networkCardInfo.getName());
	}

	public void loadFilePacket(NetworkCardInfo networkCardInfo) throws InterruptedException {

		log.info("loadFilePacket 网卡 {} 正在开启抓包ing.....",networkCardInfo.getName());

		if(corePcapPacketHandler==null){
			corePcapPacketHandler=new CorePcapPacketHandler(networkCardInfo);
			corePcapPacketHandler.initPcapPacketHandler();

		}
		networkCardInfo.setPcapPacketHandler(corePcapPacketHandler);

		try {
//			while(networkCardInfo.getPcap()!=null && (  networkCardInfo.getNetworkCaptureStaus()== PRE_RUN || networkCardInfo.getNetworkCaptureStaus()==StaticVar.NETWORKCARD_STATUS.AFTER_RUN) ) {
				networkCardInfo.setNetworkCaptureStaus(RUNNING);
				//0标识不断获取数据包  参数 cnt为指定的捕获包的个数 	//cnt=-1,无限捕获 //cnt=0，捕获所有数据包，直到读取到EOF
//			networkCardInfo.getPcap().loop(0,pcapPacketHandler,"jnetpcap");
//			 之前设置的0
//					networkCardInfo.getPcap().loop(0, networkCardInfo.getPcapPacketHandler(), networkCardInfo.getName());
//				log.warn("--{}--------------->><<<<<<>>>>>>>>{}",networkCardInfo.getPcapPacketHandler(),networkCardInfo.getName());
//					networkCardInfo.getPcap().loop(0, networkCardInfo.getPcapPacketHandler(), networkCardInfo.getName());
				log.info("----{}------ccccccccc-->>>>>loadFilePacket 网卡  正在开启抓包ing.....",networkCardInfo.getPcapPacketHandler());
				int result=networkCardInfo.getPcap().loop(appConfig.getPcapLoopSize(), networkCardInfo.getPcapPacketHandler(), networkCardInfo.getName());
				log.info("----------------------------------->>>>>loadFilePacket 网卡 {} 返回的结果：{}正在开启抓包ing.....",networkCardInfo.getName(),result);
				networkCardInfo.setNetworkCaptureStaus(StaticVar.NETWORKCARD_STATUS.AFTER_RUN);
//			}
		}catch (Exception e){
			networkCardInfo.setNetworkCaptureStaus(StaticVar.NETWORKCARD_STATUS.RUN_EXCEPTION);
			log.error("loadFilePacket 网卡 {} 抓包出现异常",networkCardInfo.getName(),e);
		}
		log.info("--->>loadFilePacket 网卡 {} 已正常结束本轮抓包,退出循环。",networkCardInfo.getName());
	}
	
	// centos 7无法获取mac地址
	public boolean canGtSystemPlatformMAC() {
		return !System.getProperty("os.name").toLowerCase().contains("linux");
	}
	 String ip= null,hostName= null;
	public void showSystemPlatformInfo() {
		 InetAddress addr; 
		try {
			props = System.getProperties();
			addr = InetAddress.getLocalHost();
			   ip = addr.getHostAddress().toString(); //获取本机ip
	           hostName = addr.getHostName().toString(); //获取本机计算机名称
		} catch (UnknownHostException e) {
		log.error("showSystemPlatformInfo：",e);
		}
         
			log.info("本机IP：{} \n 本机名称:{}",ip, hostName);
			log.info("Java的运行环境版本：{}" , props.getProperty("java.version"));
	        log.info("Java的运行环境供应商：{}", props.getProperty("java.vendor"));
	        log.info("Java供应商的URL：{}", props.getProperty("java.vendor.url"));
	        log.info("Java的安装路径：{}", props.getProperty("java.home"));
	        log.info("Java的虚拟机规范版本：{}", props.getProperty("java.vm.specification.version"));
	        log.info("Java的虚拟机规范供应商：{}", props.getProperty("java.vm.specification.vendor"));
	        log.info("Java的虚拟机规范名称：{}", props.getProperty("java.vm.specification.name"));
	        log.info("Java的虚拟机实现版本：{}", props.getProperty("java.vm.version"));
	        log.info("Java的虚拟机实现供应商：{}", props.getProperty("java.vm.vendor"));
	        log.info("Java的虚拟机实现名称：{}", props.getProperty("java.vm.name"));
	        log.info("Java运行时环境规范版本：{}", props.getProperty("java.specification.version"));
	        log.info("Java运行时环境规范供应商：{}", props.getProperty("java.specification.vender"));
	        log.info("Java运行时环境规范名称：{}", props.getProperty("java.specification.name"));
	        log.info("Java的类格式版本号：{}", props.getProperty("java.class.version"));
	        log.info("Java的类路径：{}", props.getProperty("java.class.path"));
	        log.info("加载库时搜索的路径列表：{}", props.getProperty("java.library.path"));
	        log.info("默认的临时文件路径：{}", props.getProperty("java.io.tmpdir"));
	        log.info("一个或多个扩展目录的路径：{}", props.getProperty("java.ext.dirs"));
	        log.info("操作系统的名称：{}", props.getProperty("os.name"));
	        log.info("操作系统的构架：{}", props.getProperty("os.arch"));
	        log.info("操作系统的版本：{}", props.getProperty("os.version"));
	        log.info("文件分隔符：{}", props.getProperty("file.separator"));
	        //在 unix 系统中是＂／＂
	        log.info("路径分隔符：{}", props.getProperty("path.separator"));
	        //在 unix 系统中是＂:＂
	        log.info("行分隔符：{}", props.getProperty("line.separator"));
	        //在 unix 系统中是＂/n＂
	        log.info("用户的账户名称：{}", props.getProperty("user.name"));
	        log.info("用户的主目录：{}", props.getProperty("user.home"));
	        log.info("用户的当前工作目录：{}", props.getProperty("user.dir"));
			log.info("直接内存的大小:{}", JMemory.maxDirectMemory());
			log.info("软直接内存的大小:{}", JMemory.softDirectMemory());


	}
 
	@Scheduled(initialDelay = 1000,fixedDelay = 60*1000)
	public void scheduledTask() {
		log.info("总的最大直接内存大小: {} 可分配的直接内存使用的情况: {}   已使用情况：{}",JMemory.maxDirectMemory(),JMemory.availableDirectMemory(),JMemory.reservedDirectMemory());

//		log.info("scheduledTask {}",AnalysisRTP.analysisRTPs);
	 try {
//		log.info("scheduledTask {}",AnalysisRTP.analysisRTPs);
		Analysis.clearTask();
		log.debug(" Analysis  RTP size: {},SIP size: {},clientSignalling size:{} callSignallingInfo size: {}",AnalysisRTP.analysisRTPs.size(),AnalysisSIP.analysisSIPs.size(),Analysis.clientSignallingCallInfos.size(),Analysis.callSignallingInfos.size());
		}catch (Exception e) {
			log.error(" scheduledTask  error: ",e);
		}
	}  
	
	
	
	
	@Scheduled(initialDelay = 60000,fixedDelay = 24*60*60*1000)
	public void scheduledDeleteFileTask() {
	 try {
		batchDeleteTempFile();
		batchDeleteRecordFile();
		Analysis.clearTask();
		}catch (Exception e) {
			log.error(" scheduledTask  error: ",e);
		}
	}  
	public void batchDeleteRecordFile() {
		
		
		Path dir = Paths.get(appConfig.getSaveFilePath());

		if(!Files.exists(dir)){
			try {
				Files.createDirectories(dir);
			} catch (IOException e) {
				log.error(" 录音文件夹不存在，创建文件夹异常  error: {}", appConfig.getSaveFilePath(),e);
			}
		}
		try(DirectoryStream<Path> stream = Files.newDirectoryStream(dir)){
			for(Path path : stream){
		    		FileTime ft=Files.getLastModifiedTime(path);
		    		if(ft.toInstant().plus(appConfig.getRecordFileKeepDay(), ChronoUnit.DAYS).isBefore(Instant.now())) {
		    			log.debug(" 删除录音文件夹: {} ,最后一次修改时间: {}",path.getFileName(),ft.toString());
		    			deleteFile(path.toString());
		    		}
		    		
			}
			stream.close();
		}catch(Exception e){
			log.error(" 删除临时文件  error: {}", appConfig.getTempFilePath(),e);
			
		}
	}
	
	public void batchDeleteTempFile() {
		Path dir=null;
		 try {
			 if(appConfig!=null) {
				 dir = Paths.get(appConfig.getTempFilePath());
				 if(!Files.exists(dir)){
					 try {
						 Files.createDirectories(dir);
					 } catch (IOException e) {
						 log.error(" 文件不存在创建文件夹异常  error: {}", appConfig.getTempFilePath(),e);
					 }
				 }
			 }
		 }catch (Exception e) {
			 log.warn(" 临时文件夹不存在，删除临时文件  error: {}", appConfig.getTempFilePath(),e);
		}

	        try(DirectoryStream<Path> stream = Files.newDirectoryStream(dir)){
	            for(Path path : stream){
	            	deleteTempFile(path);
	            	}
	            stream.close();
	        }catch(Exception e){
	        	log.error(" 删除临时文件  error: {}", appConfig.getTempFilePath(),e);
	        	
	        }
	}
	
	public void deleteTempFile(Path path) {
			try {
    	if(path.getFileName().toString().endsWith("temp")) {
    		FileTime ft=Files.getLastModifiedTime(path);
    		long keepDay=1;
    			keepDay= appConfig.getTempFileKeepDay()*24;
    			if(keepDay<1)keepDay=1;
    		if(ft.toInstant().plus(keepDay, ChronoUnit.HOURS).isBefore(Instant.now())) {
    			log.debug(" 删除临时文件 : {} ,最后一次修改时间: {}",path.getFileName(),ft.toString());
    			path.toFile().delete();
    		}
    		}
			}catch (Exception e) {
				log.error(" 删除临时文件  error: {}", appConfig.getTempFilePath(),e);
			}
	}
	
	public void deleteFile(String path) {	 
		Path dir = Paths.get(path);
    try(DirectoryStream<Path> stream = Files.newDirectoryStream(dir)){
        for(Path sonPath : stream){
        	if(sonPath.toFile().isDirectory()) {
        		deleteFile(sonPath.toString());
        	}
        	else {
        		sonPath.toFile().delete();
        	}
        	
        	}
        dir.toFile().delete();
        stream.close();
        
    }catch(Exception e){
    	log.error(" 删除临时文件  error: {}", appConfig.getTempFilePath(),e);
    }
	}

	public void initDeviceInfo() {
		List<DeviceInfo> DeviceInfos=new ArrayList<DeviceInfo>();
		Set<String> deviceInfoSet=RedisConfig.getValues("DeviceInfo:");
		if(deviceInfoSet== null ) return;
		int recordLicCount=licRecordMaxCount,nprtdCount=licNeedPushRealTimeTransmissionDataMaxCount;
		for (String temp : deviceInfoSet) {
			String value="";
			try {
			value=RedisConfig.getRealKeyValue(temp);
			log.debug("  DeviceInfo key:{} value: {}",temp,value);
			DeviceInfo deviceInfo=JsonPathUtil.getValue(value, "$", DeviceInfo.class);
			 
			if(recordLicCount<1) {
				deviceInfo.setNeedRecord(false);
				log.warn("录音目前授权已达到最大，分机："+deviceInfo.getDeviceNumber()+"不能进行录音");
			}
			if(nprtdCount<1) {
				deviceInfo.setNprtd(false);
				log.warn("语音流推送的授权，目前已达到最大，分机："+deviceInfo.getDeviceNumber()+"不能进行录音");
			}
			if(deviceInfo.isNeedRecord()||deviceInfo.isNprtd()) {
			DeviceInfos.add(deviceInfo);
			}
			if(deviceInfo.isNeedRecord())recordLicCount--;
			if(deviceInfo.isNprtd())nprtdCount--;
			}catch (Exception e) {
				log.error("initDeviceInfo  DeviceInfo key:{} value: {}",temp,value,e);
			}
		}
		
		log.info("需要初始化的设备： {}",DeviceInfos.size());
		log.info("录音授权数量: {} 剩余授权数量： {}",licRecordMaxCount,recordLicCount);
		log.info("语音流推送授权数量: {} 剩余授权数量： {}",licNeedPushRealTimeTransmissionDataMaxCount,nprtdCount);
		log.info("通道使用总量: {}",maxChannelCount);
		
		
		// 保证尽快切换
		 ConcurrentHashMap<String,DeviceInfo> deviceInfosTemp=new ConcurrentHashMap<String, DeviceInfo>();
		 ConcurrentHashMap<String,DeviceInfo> stationDeviceInfosTemp=new ConcurrentHashMap<String, DeviceInfo>();
		 ConcurrentHashMap<String,DeviceInfo> otherDeviceInfosTemp=new ConcurrentHashMap<String, DeviceInfo>();
		for (DeviceInfo deviceInfo : DeviceInfos) {
			if(deviceInfo.getIp()!=null)
			if(deviceInfo.getIp().trim().length()>0) {
				deviceInfosTemp.put(deviceInfo.getIp().trim(), deviceInfo);
				deviceInfosTemp.put(deviceInfo.getDeviceNumber().trim(), deviceInfo);
				if(deviceInfo.getType()==DEVICE_TYPE.STATION || deviceInfo.getType()==DEVICE_TYPE.DN) {
					stationDeviceInfosTemp.put(deviceInfo.getIp().trim(), deviceInfo);
					stationDeviceInfosTemp.put(deviceInfo.getDeviceNumber().trim(), deviceInfo);
				}else {
					otherDeviceInfosTemp.put(deviceInfo.getIp().trim(), deviceInfo);
					otherDeviceInfosTemp.put(deviceInfo.getDeviceNumber().trim(), deviceInfo);
				}
				
				log.info("添加了IP {}, deviceInfo: {}",deviceInfo.getIp(),deviceInfo);
			}
			if(deviceInfo.getMac()!=null)
			if(deviceInfo.getMac().trim().length()>0) {
				deviceInfosTemp.put(deviceInfo.getMac().trim(), deviceInfo);
				deviceInfosTemp.put(deviceInfo.getDeviceNumber().trim(), deviceInfo);
				if(deviceInfo.getType()==DEVICE_TYPE.STATION || deviceInfo.getType()==DEVICE_TYPE.DN) {
					stationDeviceInfosTemp.put(deviceInfo.getIp().trim(), deviceInfo);
					stationDeviceInfosTemp.put(deviceInfo.getDeviceNumber().trim(), deviceInfo);
				}else {
					otherDeviceInfosTemp.put(deviceInfo.getIp().trim(), deviceInfo);
					otherDeviceInfosTemp.put(deviceInfo.getDeviceNumber().trim(), deviceInfo);
				}
				log.info("添加了MAC {}, deviceInfo: {}",deviceInfo.getMac(),deviceInfo);
			}
		}
		// 初始化完成后需要切换成最新的
		deviceInfos=deviceInfosTemp;
		stationDeviceInfos=stationDeviceInfosTemp;
		otherDeviceInfos=otherDeviceInfosTemp;
		log.info("加载的deviceInfos设备信息如下： {}",Tools.getjsonString(deviceInfos));
		log.info("加载的stationDeviceInfos设备信息如下： {}",Tools.getjsonString(stationDeviceInfos));
		log.info("加载的otherDeviceInfos设备信息如下： {}",Tools.getjsonString(otherDeviceInfos));
	}




	/**
	 *  所有网卡开启抓包线程
	 */
	public void networkThreadStartAll(){
		// 开启线程抓取网卡数据
		if(openNetworkCards.size()>0) {
			List<Thread> liveThread=checkLiveThread();
			for (NetworkCardInfo networkCardInfo : openNetworkCards.values()) {
				String threadName="cap-main-"+networkCardInfo.getName();
				try {
					if(networkCardInfo.isNeedReinitThread() && networkCardInfo.getLoadPacketThread()!=null){
						List<Thread> allCapThread=liveThread.stream().filter(thread->{
							return thread.getName().equals(threadName);
								}
						).collect(Collectors.toList());
                        if(allCapThread==null || allCapThread.size()<1){
							log.warn("networkThreadStartAll thread   网卡线程不存活，需要初始线程。 {} ", networkCardInfo.getName(),networkCardInfo.getLoadPacketThread().getState());
						}else if(allCapThread.size()>1){
							log.info("networkThreadStartAll thread   网卡线程存活大于1条，需要重新初始线程。 {} ", networkCardInfo.getName());
						}
						networkCardInfo.setLoadPacketThread(null);
						// 之前的线程需要处理掉。
						allCapThread.forEach(t->{
							try {
								log.info("networkThreadStartAll thread stop  网卡线程{} 正在关闭。线程ID: {} ............", networkCardInfo.getName(), t.getId());
								t.stop();
								log.info("networkThreadStartAll thread stop  网卡线程{} 已成功关闭。线程ID: {} ............", networkCardInfo.getName(), t.getId());
							} catch (Exception e) {
								log.error("networkThreadStartAll thread stop  网卡线程{} 关闭失败。线程ID: {} ............", networkCardInfo.getName(), t.getId(), e);
							}
						});



					}
					if(networkCardInfo.getLoadPacketThread()!=null && networkCardInfo.getNetworkCaptureStaus().getValue()>0){
//						 线程已经存在，并且状态不是销毁中或关闭的无需处理。
						continue;
					}

					Thread loadPacketThread;
					log.info("networkThreadStartAll Starting  networkThreadStart {} ............!!!", networkCardInfo.getName());
					loadPacketThread = new Thread(() -> {

						while (networkCardInfo.isLoadPacketThreadStart() &&networkCardInfo.getLoadPacketThread()!=null && Thread.currentThread().getId()==networkCardInfo.getLoadPacketThread().getId()) {
							try {
								networkThreadStart(networkCardInfo);
							} catch (Exception e) {
								log.error("networkThreadStartAll Starting  networkThreadStart fail {} ............", networkCardInfo.getName());
							}
						}
						log.info("networkThreadStartAll Starting  networkThreadStart 抓包线程退出循环 <<<<<<< {} ............", networkCardInfo.getName());
					});
					loadPacketThread.setName(threadName);
					loadPacketThread.setPriority(Thread.MAX_PRIORITY - 2);
					networkCardInfo.setLoadPacketThread(loadPacketThread);
					loadPacketThread.start();
					log.info("networkThreadStartAll Started  networkThreadStart 已开启线程。 {} 线程ID: {} ............", networkCardInfo.getName(),loadPacketThread.getId());
				}catch (Exception e){
					log.error("networkThreadStartAll Starting  开启抓包线程失败。 fail {} ............", networkCardInfo.getName(),e);
				}
			}

		}else {
			log.info("networkThreadStartAll 你没有选择网卡，请配置IP地址，对IP地址的网卡进行抓包，V4，V6均可,IP相同将抓最后一个匹配的网卡 !!!");
		}





	}



	/**
	 *  所有抓包文件开启线程
	 */
	public void networkFileThreadStartAll(){
		// 开启线程抓取网卡数据
		if(openNetworkFileCard==null) {
			return ;
		}
		if(openNetworkFileCard.getLoadPacketThread()!=null){
			return;
		}
		log.info("networkFileThreadStartAll 配置读取{}文件夹下的抓包文件 !!!",openNetworkFileCard.getHardwareAddress());
			List<Thread> liveThread=checkLiveThread();
				String threadName="cap-main-"+openNetworkFileCard.getName();
				try {
					if(openNetworkFileCard.isNeedReinitThread() && openNetworkFileCard.getLoadPacketThread()!=null){
						List<Thread> allCapThread=liveThread.stream().filter(thread->{
									return thread.getName().equals(threadName);
								}
						).collect(Collectors.toList());
						if(allCapThread==null || allCapThread.size()<1){
							log.warn("networkFileThreadStartAll thread   网卡线程不存活，需要初始线程。处理的文件 {} ", openNetworkFileCard.getHardwareAddress(),openNetworkFileCard.getLoadPacketThread().getState());
						}else if(allCapThread.size()>1){
							log.info("networkFileThreadStartAll thread   网卡线程存活大于1条，需要重新初始线程。处理的文件 {} ", openNetworkFileCard.getHardwareAddress());
						}
						openNetworkFileCard.setLoadPacketThread(null);
						// 之前的线程需要处理掉。
						allCapThread.forEach(t->{
							try {
								log.info("networkFileThreadStartAll thread stop  文件名： {} 正在关闭。线程ID: {} ............", openNetworkFileCard.getHardwareAddress(), t.getId());
								t.stop();
								log.info("networkFileThreadStartAll thread stop   文件名： {} 已成功关闭。线程ID: {} ............", openNetworkFileCard.getHardwareAddress(), t.getId());
							} catch (Exception e) {
								log.error("networkFileThreadStartAll thread stop   文件名：{} 关闭失败。线程ID: {} ............", openNetworkFileCard.getHardwareAddress(), t.getId(), e);
							}
						});



					}

					Thread loadPacketThread;
					log.info("networkFileThreadStartAll Starting  networkThreadStart  文件名：{} ............!!!", openNetworkFileCard.getHardwareAddress());
					loadPacketThread = new Thread(() -> {

						while (openNetworkFileCard.isLoadPacketThreadStart() &&openNetworkFileCard.getLoadPacketThread()!=null && Thread.currentThread().getId()==openNetworkFileCard.getLoadPacketThread().getId()) {
							try {
								networkFileThreadStart(openNetworkFileCard);
							} catch (Exception e) {
								log.error("networkFileThreadStartAll Starting  networkThreadStart fail 文件名： {} ............", openNetworkFileCard.getHardwareAddress());
							}
						}
						log.info("networkFileThreadStartAll Starting  networkThreadStart 抓包线程退出循环 <<<<<<<  文件名：{} ............", openNetworkFileCard.getHardwareAddress());
					});
					loadPacketThread.setName(threadName);
					loadPacketThread.setPriority(Thread.MAX_PRIORITY - 2);
					openNetworkFileCard.setLoadPacketThread(loadPacketThread);
					loadPacketThread.start();
					log.info("networkFileThreadStartAll Started  networkThreadStart 已开启线程。文件名： {} 线程ID: {} ............", openNetworkFileCard.getHardwareAddress(),loadPacketThread.getId());
				}catch (Exception e){
					log.error("networkFileThreadStartAll Starting  开启抓包线程失败。 fail。 文件名： {} ............", openNetworkFileCard.getHardwareAddress(),e);
				}
	}

	/**
	 * 网卡线程打开开始工作。
	 * @param networkCardInfo 需要 开启的网卡信息
	 */

	public void networkThreadStart(NetworkCardInfo networkCardInfo){
		try {
			networkCardInfo.setReCapCount(networkCardInfo.getReCapCount()+1);
			log.info("CaptureNetPacket Application 正在打开网卡中 capture networkCardName {} 当前线程ID: {} 重新计数次数: {} net packet ............", networkCardInfo.getName(),networkCardInfo.getLoadPacketThread().getId(),networkCardInfo.getReCapCount());
			if(networkCardInfo.getPcap()==null) {
				openDrive(networkCardInfo);
			}
			/**
			 * TODO 做其他网卡抓包前的事情。
			 以后分开到多线程时需要加 PRE_RUN 状态，并做其他事情。
			 */
			networkCardInfo.setNetworkCaptureStaus(PRE_RUN);
			while (networkCardInfo.getPcap()!=null && networkCardInfo.isStartCapture() && networkCardInfo.getNetworkCaptureStaus()==PRE_RUN && networkCardInfo.getLoadPacketThread()!=null && Thread.currentThread().getId()==networkCardInfo.getLoadPacketThread().getId()) {
				log.info("CaptureNetPacket Application Start 开始捕获网卡数据中,数据开始收集中........，capture networkCardName {} net packet ............", networkCardInfo.getName());
				//							 开始抓包，线程相当于堵塞
				loadPacket(networkCardInfo);
				log.info("CaptureNetPacket Application Start 捕获网卡数据结束一轮，capture networkCardName {} net packet ............", networkCardInfo.getName());
			}
		}catch (Exception e){
			log.error("CaptureNetPacket Application Start 捕获网卡数据结束，capture networkCardName {} net packet ............", networkCardInfo.getName());
		}
		log.info("CaptureNetPacket networkThreadStart 捕获网卡数据结束，退出抓包循环<<<<<<，capture networkCardName {} net packet ............", networkCardInfo.getName());
	}

	/**
	 * 读取抓包线程打开开始工作。
	 * @param networkCardInfo 需要 开启的网卡信息
	 */

	public void networkFileThreadStart(NetworkCardInfo networkCardInfo){
		while(networkCardInfo.isLoadPacketThreadStart()) {

			networkFileHandel(networkCardInfo);
			try {
             Thread.sleep(appConfig.getFileScanIntervalTime());
			} catch (Exception e) {
				log.warn("networkFileThreadStart 文件处理休眠失败",e);
			}
		}
	}

	/**
	 *  对指定具体的珠宝文件进行处理。
	 * @param networkCardInfo
	 */
	public void networkFileHandel(NetworkCardInfo networkCardInfo){
		networkCardInfo.setReCapCount(networkCardInfo.getReCapCount()+1);
		log.info("networkFileHandel Application 正在扫描文件夹中 capture 处理文件夹 {} 当前线程ID: {} 重新计数次数: {} net packet ............", appConfig.getFilePath(),networkCardInfo.getLoadPacketThread().getId(),networkCardInfo.getReCapCount());

		List<Path> pcapFilesSort=null;

		try{
			 List<Path> pcapFiles=searchPcapFiles(appConfig.getFilePath());
			pcapFilesSort=pcapFiles.stream().sorted((p1,p2) -> {
				try {
					if(Files.getLastModifiedTime(p1).toMillis()-Files.getLastModifiedTime(p2).toMillis()>0){
//						log.warn("{} -->>>: {}--------->>>>>>>-------{}  --->>:  {}",p1.getFileName(),Files.getLastModifiedTime(p1).toMillis(),p2.getFileName(),Files.getLastModifiedTime(p2).toMillis());
						return 1;
					}
				} catch (IOException e) {
					log.warn("排序时间时，获取文件时间失败 文件1： {} 文件2： {} 文件处理休眠失败",p1.getFileName(),p2.getFileName(),e);
				}
				return -1;
			}).collect(Collectors.toList());

		}catch (Exception e){
			log.warn("networkFileHandel Application  扫描文件夹中出现异常 capture 处理文件夹 {} 当前线程ID: {} 重新计数次数: {} net packet ............", appConfig.getFilePath(),networkCardInfo.getLoadPacketThread().getId(),networkCardInfo.getReCapCount());

		}


		if(pcapFilesSort==null || pcapFilesSort.size()<1){
			return;
		}
		     pcapFilesSort.forEach(path-> {
					// 按顺序处理文件。
//				 String fileName=path.toAbsolutePath().toString();
				 String fileName=path.getFileName().toString();
				 try {
						if (networkCardInfo.getPcap() == null) {
							openFileDrive(networkCardInfo, fileName);
						}
						/**
						 *
						 以后分开到多线程时需要加 PRE_RUN 状态，并做其他事情。
						 */
						networkCardInfo.setNetworkCaptureStaus(PRE_RUN);
						if (networkCardInfo.getPcap() != null && networkCardInfo.isStartCapture() && networkCardInfo.getNetworkCaptureStaus() == PRE_RUN && networkCardInfo.getLoadPacketThread() != null && Thread.currentThread().getId() == networkCardInfo.getLoadPacketThread().getId()) {
							log.info("networkFileHandel Application Start 开始捕获网卡数据中,数据开始收集中........，capture networkCardName {} net packet ............", fileName);
							//							 开始抓包，线程相当于堵塞
							loadFilePacket(networkCardInfo);
							log.info("networkFileHandel Application Start 捕获网卡数据结束一轮，capture networkCardName {} net packet ............", fileName);
						}
					} catch (Exception e) {
						log.error("networkFileHandel Application Start 捕获网卡数据结束，capture networkCardName {} net packet ............", fileName);
					}

					// 读取完成后关闭文件读取下一个抓包文件。。
					log.info("networkFileHandel networkThreadStart 捕获网卡数据结束，退出抓包循环<<<<<<，capture networkCardName {} net packet ............", fileName);
					try {
						if (networkCardInfo.getPcap() != null) {
							networkCardInfo.getPcap().close();
							networkCardInfo.setPcap(null);
							log.info("networkFileHandel {} 网卡关闭成功 !!! Pcap close 。当前线程ID: {}", fileName, networkCardInfo.getLoadPacketThread().getId());
						} else {
							log.info("networkFileHandel {} 网卡关闭成功 !!! 需要只重新初始化线程。当前线程ID: {}", fileName, networkCardInfo.getLoadPacketThread().getId());
						}
					} catch (Exception e) {
						log.warn("networkFileHandel {} 网卡关闭失败!!!", fileName, e);
					}
				}
          );


	}
	/**
	 * 查找所有的pcap 文件
	 * @param path
	 */
	public List<Path> searchPcapFiles(String path){
		List<Path> pcapFiles=new ArrayList<>();
		try {
			Path dir = Paths.get(path);
			try(DirectoryStream<Path> stream = Files.newDirectoryStream(dir)){
				for(Path sonPath : stream){
					if(sonPath.toFile().isDirectory()) {
						pcapFiles.addAll(searchPcapFiles(sonPath.toString()));
					}
					else {
							String fileExtension = sonPath.getFileName().toString().substring(sonPath.getFileName().toString().lastIndexOf(".") + 1);
							if(StringUtils.hasText(fileExtension)){
								if(fileExtension.equalsIgnoreCase("pcap")||fileExtension.equalsIgnoreCase("cap")){
						                          pcapFiles.add(sonPath);
								}
							}
					}
				}
				stream.close();
			}catch(Exception e){
				log.warn(" 查找文件夹下的文件失败，文件名:{}  error: {}", path,e);
			}
		} catch (Exception e) {
			log.warn("searchPcapFiles 查找文件失败",e);
		}
		return pcapFiles;
	}



	/**
	 *  检查网卡状态并处理
	 */
	 public void checkNetworkAndHandel(){

		 int timeOutPacketSleep= 3000;
//               Pcap
			 if (openNetworkCards.size() > 0  )  {
//				 log.debug("checkNetworkAndHandel 正在检查网卡状态，检查间隔时间:{}毫秒，网卡超时时间 {}毫秒。 v1",timeOutPacketSleep,timeOutPacket);
				 for (NetworkCardInfo networkCardInfo : openNetworkCards.values()) {
//					 主动检查
					  	 /* 通过查看返回值pcap_activate()进行检查。该pcap_activate()手册页说：
					 pcap_activate()成功返回0，而不警告，PCAP_WARNING_PROMISC_NOTSUP对不上成功支持混杂模式如果请求混杂模式，PCAP_WARNING与其他任何警告的设备上的成功，PCAP_ERROR_ACTIVATED如果句柄已被激活，PCAP_ERROR_NO_SUCH_DEVICE如果创建句柄时指定的捕获源不存在，PCAP_ERROR_PERM_DENIED如果进程没有权限打开捕获源，PCAP_ERROR_RFMON_NOTSUP如果指定了监视器模式但捕获源不支持监视模式，PCAP_ERROR_IFACE_NOT_UP如果捕获源未启动，并且PCAP_ERROR发生了另一个错误。如果返回PCAP_WARNING或PCAP_ERROR，则可以调用pcap_geterr()或pcap_perror()并使用p作为获取或显示描述警告或错误的消息的参数。如果返回PCAP_WARNING_PROMISC_NOTSUP,PCAP_ERROR_NO_SUCH_DEVICE或PCAP_ERROR_PERM_DENIED，则可调用pcap_geterr()或pcap_perror()作为获取或显示消息的参数，其中提供了有关该问题的其他详细信息，如果该问题出乎意料，可能对调试问题有用。
					*/

					/* if(networkCardInfo.getPcap()!=null && networkCardInfo.getNetworkCaptureStaus().getValue()>-1) {
						 try {
							 int errCode = networkCardInfo.getPcap().activate();
							 if (errCode < 1) {
								 log.warn("checkNetworkAndHandel 主动 activate 网卡 {} ,检查到网卡出现故障，关闭网卡。出现错误消息: {}", networkCardInfo.getName(), errCode);
								 String errInfo = networkCardInfo.getPcap().getErr();
								 if (StringUtils.hasText(errInfo)) {
									 log.warn("checkNetworkAndHandel 主动 activate 检查到网卡出现故障，网卡 {} 出现了错误消息: {}", networkCardInfo.getName(), networkCardInfo.getLastError());
								 }
						*//* networkCardInfo.getLoadPacketThread().interrupt();
						 // 理论上退出堵塞继续
						 networkCardInfo.getPcap().breakloop();
						 networkCardInfo.getLoadPacketThread().interrupt();
						 if(networkCardInfo.getPcap()!=null) {
							 closeDrive(networkCardInfo);
						 }*//*
							 }
						 }catch (Exception e){
							 log.error("checkNetworkAndHandel 主动 activate 网卡 {} ,检查到网卡出现故障，关闭网卡。 捕获到异常。", networkCardInfo.getName(), e);
						 }
					 }*/
					 try {
						 Thread.sleep(timeOutPacketSleep);
					 }catch (Exception e){
						 log.warn("checkNetworkAndHandel 守护线程休眠失败",e);
					 }
					 if (networkCardInfo.getNetworkCaptureStaus()==RUNNING && timeOutPacket>0 && Duration.between(networkCardInfo.getLastRecivePacketTime(), LocalDateTime.now()).toMillis()>timeOutPacket-1) {
						 log.warn("checkNetworkAndHandel 网卡: {} 在 {}毫秒未收到数据包，正在准备重新初始化。最后接受包的时间: {} ",networkCardInfo.getName(),timeOutPacket,networkCardInfo.getLastRecivePacketTime().format(Tools.dfFull));
						 try {
							 networkCardInfo.getLoadPacketThread().interrupt();
							 // 理论上退出堵塞继续
							 networkCardInfo.getPcap().breakloop();
							 networkCardInfo.getLoadPacketThread().interrupt();
							 log.error("checkNetworkAndHandel 网卡: {} 在 {}毫秒未收到数据包，正在准备重新初始化。最后接受包的时间: {} 线程id: {} 状态:{}",networkCardInfo.getName(),timeOutPacket,networkCardInfo.getLastRecivePacketTime().format(Tools.dfFull),networkCardInfo.getLoadPacketThread().getId(),networkCardInfo.getLoadPacketThread().getState());
						 }catch (Exception e){
							 log.error("网卡: {} 在 {}毫秒未收到数据包，正在重新初始化,打破收包循环，重新开始收包。最后接受包的时间: {} ",networkCardInfo.getName(),timeOutPacket,networkCardInfo.getLastRecivePacketTime().format(Tools.dfFull));
						 }

						 // 判断是否能正常退出抓包循环
						 checkLoopNormalEnd(networkCardInfo);
					 }else {
						 log.debug("checkNetworkAndHandel 网卡: {} 在 {}毫秒已收到数据包。 网卡线程计数值{}。 最后接受包的时间: {} ",networkCardInfo.getName(),timeOutPacket,networkCardInfo.getReCapCount(),networkCardInfo.getLastRecivePacketTime().format(Tools.dfFull));
						 networkCardInfo.setReCapCount(1);
					 }



//					 log.debug("checkNetworkAndHandel 正在获取网卡错误信息: {}   最后接受数据的时间:{}",networkCardInfo.getName(),networkCardInfo.getLastRecivePacketTime());

                     if(networkCardInfo.getPcap()!=null && networkCardInfo.getNetworkCaptureStaus().getValue()>-1) {
						 String errInfo = networkCardInfo.getPcap().getErr();
						 if (StringUtils.hasText(errInfo)) {
							 if (!errInfo.equals(networkCardInfo.getLastError())) {
								 networkCardInfo.setLastError(errInfo);
								 log.warn("checkNetworkAndHandel 网卡 {} 出现错误消息: {}", networkCardInfo.getName(), networkCardInfo.getLastError());
							 }
						 }
					 }

//						  log.info("网卡信息 {}", networkCardInfo);
				 }
			 }
			 try {
				 Thread.sleep(timeOutPacketSleep);
			 }catch (Exception e){
				 log.error("checkNetworkAndHandel 守护线程休眠失败",e);
			 }


	 }

	/**
	 * 通过状态和时间判断是否为正常结束抓包循环。
	 * @param networkCardInfo
	 */
    public void checkLoopNormalEnd(NetworkCardInfo networkCardInfo){
		networkCardInfo.setNeedReinitThread(false);
		 LocalDateTime beforeLastRecivePacketTime=networkCardInfo.getLastRecivePacketTime();
		log.info("CaptureNetPacket Application 等待打破循环后，正常关闭捕获网卡循环中 capture networkCardName {} net packet ............",networkCardInfo.getName());
		for (int i=0;i<250;i++){
			 try {
				 networkCardInfo.getPcap().breakloop();

				 networkCardInfo.getLoadPacketThread().interrupt();
				 Thread.sleep(40);
				 if(networkCardInfo.getNetworkCaptureStaus()== RUNNING && !beforeLastRecivePacketTime.equals(networkCardInfo.getLastRecivePacketTime())){
//					 收到不一样的包，说明有数据返回了，不需要重新初始化线程。
					 return ;
				 }
			 }catch (Exception e){
				 log.error("checkLoopNormalEnd 线程休眠失败",e);
				 networkCardInfo.setNeedReinitThread(false);
			 }
		 }

		log.warn("checkNetworkAndHandel 网卡退出本轮循环,非正常循环关闭: {} 在 {}毫秒未收到数据包，等待重新初始化。",networkCardInfo.getName(),timeOutPacket);
		closeDrive(networkCardInfo);
		networkCardInfo.getLoadPacketThread().interrupt();
	}


	/**
	 *     处理读取文件的进程
	 */
	public void pcapFileAndHandel(){
//		Pcap aa=Pcap.openOffline("","");
//		aa.setFilter();
//		aa.close();
//
////aa
	}

	/**
	 * 获取存活的线程
	 * @return
	 */
	public static List<Thread>  checkLiveThread(){
		List<Thread> liveThread=new ArrayList<>();
		try {
			ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
			ThreadGroup parentGroup;
			while ((parentGroup = rootGroup.getParent()) != null) {
				rootGroup = parentGroup;
			}
			// 激活的线程数再加一倍，防止枚举时有可能刚好有动态线程生成
			int slackSize = rootGroup.activeCount() * 2;
			Thread[] slackThreads = new Thread[slackSize];
			// 获取根线程组下的所有线程，返回的actualSize便是最终的线程数
			int actualSize = rootGroup.enumerate(slackThreads);

			Thread[] atualThreads = new Thread[actualSize];
			// 复制slackThreads中有效的值到atualThreads
			System.arraycopy(slackThreads, 0, atualThreads, 0, actualSize);
			log.info("存活线程有: {} " , atualThreads.length);
			for (Thread thread : atualThreads) {
				liveThread.add(thread);
				log.debug("存活的线程有 : {}  名称：{} 属于: {} 状态: {} 优先级: {}" , thread.getId(),thread.getName(),thread.getThreadGroup(),thread.getState(),thread.getPriority());
			}
		}catch (Exception e){
			log.warn("打印所有线程失败:  " ,e);
		}
		return liveThread;
	}
}
